/*
	Copyright 2011 Dario Seitel, Sebastian Mayer. All rights reserved.

	Redistribution and use in source and binary forms, with or without modification, are
	permitted provided that the following conditions are met:

	   1. Redistributions of source code must retain the above copyright notice, this list of
		  conditions and the following disclaimer.

	   2. Redistributions in binary form must reproduce the above copyright notice, this list
		  of conditions and the following disclaimer in the documentation and/or other materials
		  provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
	WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
	FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
	ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
	ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	The views and conclusions contained in the software and documentation are those of the
	authors and should not be interpreted as representing official policies, either expressed
	or implied, of <copyright holder>.
*/

#ifndef GAMEENGINE_H_
#define GAMEENGINE_H_

#include <list>
#include "entities/Player.h"
#include "AribaNode.h"

using namespace std;

class Shot;
class Collectible;
class IMapGenerator;
class Region;

// max map size (in tiles, currently only needed for map generator)
#define MAP_WIDTH_MAX 1000
#define MAP_HEIGHT_MAX 1000
// region size (in tiles)
#define REGION_WIDTH 10
#define REGION_HEIGHT 10
#define MAP_TILE_SIZE 40

#define SCREEN_WIDTH 600
#define SCREEN_HEIGHT 600

#define DEBUG_FEATURE_WIREFRAME 1
#define DEBUG_FEATURE_PLAYER_TERRAIN_NOCLIP 2
#define DEBUG_FEATURE_COLLISION_BOXES 4
#define DEBUG_FEATURE_REGION_BORDERS 8

class GameEngine {
public:
	virtual ~GameEngine();
	static GameEngine &get();

	virtual void startGame();
	virtual void run();
	virtual Player &getPlayer();
	virtual Entity*** getRegionMap(int x, int y);
	virtual Entity*** getMatchingRegionMap(float x, float y);
	virtual list<Entity*> &getRenderedObjects();
	virtual list<Player*> &getPlayers();
	virtual bool isEnabledDebugFeature(int debugFeature);
	virtual bool checkCollisionAgainstTerrain(float dx, float dy, Entity &entity);
	virtual int getMapWidth();
	virtual int getMapHeight();
	virtual void setMapWidth(int mapWidth);
	virtual void setMapHeight(int mapHeight);
	virtual void manageRegion(int managedRegionX, int managedRegionY, bool isBackup);
	virtual bool isManagingRegion(int regionX, int regionY);
	virtual int getManagedRegionX();
	virtual int getManagedRegionY();
	virtual int getCurrentRegionX();
	virtual int getCurrentRegionY();
	virtual bool getIsBackup();
	virtual AribaNode &getAribaNode();
	virtual int calcGroupID(int, int);
	virtual Region* getRegion(int x, int y);
	virtual list<Region*> getJoinedRegions();
	virtual void replaceRegionMap(Entity*** map, int regionX, int regionY);
	virtual IMapGenerator* getMapGenerator();

	static bool checkCollisionAABB(Entity &a, Entity &b);
	static int xToTileX(float x);
	static int yToTileY(float y);
	static int tileXtoRegionTileX(int x);
	static int tileYtoRegionTileY(int y);
	static int xToRegionTileX(float x);
	static int yToRegionTileY(float y);

	virtual void addObject(Entity* object);
	virtual void removeObject(Entity* object);
	virtual void addObject(Shot* object);
	virtual void removeObject(Shot* object);
	virtual void addObject(Player* object);
	virtual void removeObject(Player* object);
	virtual void addObject(Collectible* object);
	virtual void removeObject(Collectible* object);

	virtual void addNewPlayer(string, float, float);
	virtual Player* findPlayer(string name);
	virtual void calcSpwanPosition(float*, float*);
	virtual void checkToBeamPlayer(Player *player, float x, float y);
	virtual void checkToBeamPlayer(Player *player, float angle, float x, float y);


	virtual void joinRegion(Region* region);

	static string confPath;

private:
	GameEngine();

	virtual void toggleDebugFeature(int debugFeature);
	virtual void manageGroupMemberships();
	virtual void leaveRegion(Region* region);
	virtual bool isRegionJoined(Region* region);
	virtual void calcPlayerPositions(float frameTime);

	Player player;
	Region*** regions;
	IMapGenerator* mapGenerator;
	list<Entity*> renderedObjects;
	list<Shot*> shots;
	list<Player*> players;
	list<Collectible*> collectibles;
	list<Region*> joinedRegions;
	bool enableDebug;
	bool gameRunning;
	int enabledDebugFeatures;
	int mapWidth;
	int mapHeight;
	int managedRegionX;
	int managedRegionY;
	bool isBackup;

	//Ariba reference
	AribaNode * aribaNode;
};


#endif /* GAMEENGINE_H_ */
